using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Framework;

public class MessageBox : MonoBehaviour
{
    [SerializeField]
    Button btnOK;
    [SerializeField]
    Button btnCancel;
    [SerializeField]
    Button btnClose;
    [SerializeField]
    TMPro.TextMeshProUGUI okText;
    [SerializeField]
    TMPro.TextMeshProUGUI cancelText;
    [SerializeField]
    TMPro.TextMeshProUGUI msgText;
    [SerializeField]
    StateEventMachine eventMachine;

    private void Awake()
    {
        btnOK.onClick.AddListener(OnOK);
        btnCancel.onClick.AddListener(OnCancel);
        btnClose.onClick.AddListener(OnCancel);
    }

    private void OnDestroy()
    {
        btnOK.onClick.RemoveListener(OnOK);
        btnCancel.onClick.RemoveListener(OnCancel);
        btnClose.onClick.AddListener(OnCancel);
    }

    void OnOK()
    {
        this.data.state = MsgBoxRunningState.Destroying;
        this.data.actionOK?.Invoke();
        Destroy(this.gameObject);
    }

    void OnCancel()
    {
        this.data.state = MsgBoxRunningState.Destroying;
        this.data.actionCancel?.Invoke();
        Destroy(this.gameObject);
    }

    MessageBoxData data;
    public MessageBox Setup(MessageBoxData data)
    {
        this.data = data;
        okText.text = this.data.ok;
        cancelText.text = this.data.cancel;
        msgText.text = this.data.content;
        eventMachine.Set(data.msgBoxType.ToString());
        return this;
    }
}

public enum MsgBoxType
{
    OK_CANCEL_CLOSE = 0,
    OK_CANCEL = 1,
    OK = 2,
}

public enum MsgBoxRunningState
{
    WAIT,
    Loading,
    Interacting,
    Destroying,
}

public class MessageBoxData
{
    public MsgBoxType msgBoxType;
    public string ok;
    public string cancel;
    public string content;
    public System.Action actionOK,actionCancel;
    public string res;
    public YooAsset.AssetHandle runningHandle;
    public MsgBoxRunningState state;
    public void Reset()
    {
        msgBoxType = MsgBoxType.OK_CANCEL_CLOSE;
        ok = string.Empty;
        cancel = string.Empty;
        content = string.Empty;
        actionOK = null;
        actionCancel = null;
        runningHandle = null;
        state = MsgBoxRunningState.WAIT;
    }
}

public class MessageBoxQueueManager
{
    static MessageBoxQueueManager s_instance = new MessageBoxQueueManager();
    public static MessageBoxQueueManager Instance => s_instance;
    SimpleObjectPool<MessageBoxData> msgBoxPool = new SimpleObjectPool<MessageBoxData>(() => new(), 16);
    Queue<MessageBoxData> msgQueue = new Queue<MessageBoxData>(32);

    MessageBoxData runningData;

    public void Clear()
    {
        msgQueue.Clear();
    }

    public void Update()
    {
        if (runningData != null)
        {
            switch(runningData.state)
            {
                case MsgBoxRunningState.Loading:
                    {
                        if (!runningData.runningHandle.IsDone)
                        {
                            return;
                        }
                        if (!string.IsNullOrEmpty(runningData.runningHandle.LastError))
                        {
                            runningData.state = MsgBoxRunningState.Destroying;
                            return;
                        }
                        var handle = (GameObject)Object.Instantiate(runningData.runningHandle.AssetObject);
                        var msgBox = handle.GetComponent<MessageBox>();
                        msgBox.Setup(runningData);
                        UIFrameManager.Instance.SetParent(handle.transform);
                        runningData.state = MsgBoxRunningState.Interacting;
                        break;
                    }
                case MsgBoxRunningState.Destroying:
                    {
                        runningData.runningHandle.Dispose();
                        runningData.Reset();
                        msgBoxPool.Put(runningData);
                        runningData = null;
                        break;
                    }
            }
            return;
        }

        if(msgQueue.Count > 0)
        {
            runningData = msgQueue.Dequeue();
            var runningHandle = YooAsset.YooAssets.LoadAssetAsync<GameObject>(runningData.res);
            if(null == runningHandle)
            {
                runningData.Reset();
                msgBoxPool.Put(runningData);
                runningData = null;
                return;
            }
            runningData.runningHandle = runningHandle;
            runningData.state = MsgBoxRunningState.Loading;
        }
    }

    void PopupMessage(string msg,string ok,string cancel,System.Action actionOK, System.Action actionCancel,string res,MsgBoxType msgBoxType)
    {
        var msgData = msgBoxPool.Get();
        msgData.content = msg;
        msgData.ok = ok;
        msgData.cancel = cancel;
        msgData.actionOK = actionOK;
        msgData.actionCancel = actionCancel;
        msgData.res = res;
        msgData.msgBoxType = msgBoxType;
        msgQueue.Enqueue(msgData);
    }

    public void PopupMessage(int msgId,System.Action actionOK = null, System.Action actionCancel = null)
    {
        if (msgId < 0)
            msgId = -msgId;

        unsafe
        {
            var t = TableManager.GetTable<Framework.Table.MessageTable>();
            var msgTableItem = t.GetItem(msgId);
            if (null != msgTableItem)
            {
                var ok = t.getStringValue(msgTableItem->_OK_pos, msgTableItem->_OK_count);
                var cancel = t.getStringValue(msgTableItem->_Cancel_pos, msgTableItem->_Cancel_count);
                var content = t.getStringValue(msgTableItem->_Content_pos, msgTableItem->_Content_count);
                var res = t.getStringValue(msgTableItem->_resName_pos, msgTableItem->_resName_count);
                PopupMessage(content, ok, cancel, actionOK, actionCancel, res, (MsgBoxType)msgTableItem->State);
            }
        }
    }
}
